package org.itboys.fuzion.service;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.itboys.commons.utils.random.RandomUtils;
import org.itboys.commons.utils.time.TimeUtils;
import org.itboys.framework.resource.ResourceHolder;
import org.itboys.fuzion.constant.FuzionConstants;
import org.itboys.fuzion.dto.FuzionMemberRedisDto;
import org.itboys.fuzion.entity.FuzionMember;
import org.itboys.fuzion.entity.IncomeExpenditureRecords;
import org.itboys.fuzion.entity.WithdrawsRecords;
import org.itboys.fuzion.mysql.orm.FuziongMemberStatistics;
import org.itboys.fuzion.mysql.service.FuziongMemberStatisticsService;
import org.itboys.fuzion.tools.ClientCustomSSL;
import org.itboys.fuzion.tools.SendInfoThread;
import org.itboys.mongodb.core.MongoDataSource;
import org.itboys.mongodb.service.BaseService;
import org.itboys.mongodb.utils.page.Page;
import org.itboys.weixin.constant.WeixinConstants;
import org.itboys.weixin.entity.CompanyPayConfig;
import org.itboys.weixin.entity.WeixinConfig;
import org.itboys.weixin.entity.WeixinSendInfo;
import org.itboys.weixin.entity.WeixinShopConfig;
import org.itboys.weixin.service.WeixinConfigService;
import org.itboys.weixin.service.WeixinSendInfoService;
import org.itboys.weixin.tools.CompanyPayUtils;
import org.itboys.weixin.tools.SignUtil;
import org.itboys.weixin.tools.XMLUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;

/**
 * 申请提现记录
 * @author weisky
 *
 * 2016年4月19日
 */
@Service
public class WithdrawsRecordsService extends BaseService<WithdrawsRecords, Long>{

	private static final long serialVersionUID = 1L;
	
	@Autowired
	private FuzionMemberService fuzionMemberService;
	@Autowired
	private FuziongMemberStatisticsService fuziongMemberStatisticsService;
	@Autowired
	private IncomeExpenditureRecordsService incomeExpenditureRecordsService;
	@Autowired
	private WeixinConfigService weixinConfigService;
	@Autowired
	private ResourceHolder resourceHolder;
	@Autowired
	private WeixinSendInfoService weixinSendInfoService;
	
	@Resource(name = "memberDS")
	private MongoDataSource ds;
	
	@Override
	protected MongoDataSource getMongoDataSource() {
		return ds;
	}
	
	/**
	 * 带有分页组装信息
	 * @param param
	 * @param request
	 * @return
	 */
	public Page<WithdrawsRecords> listByPage(Map<String, Object> param, HttpServletRequest request){
		Page<WithdrawsRecords> page = super.pageQuery(param, request);
		if(page != null && page.getData() != null){
			page.getData().forEach(pg -> {
				FuzionMember fm = fuzionMemberService.getById(pg.getMemberId());
				if(fm != null){
					String name = (StringUtils.isBlank(fm.getNickname()) ? fm.getUsername() : fm.getNickname());
					pg.setNickName(name);
				}
				pg.setMoney(pg.getMoney()/100);//将分转为元
			});
		}
		return page;
	}
	
	/**
	 * 微信端的提现操作逻辑
	 * @param memberId
	 * @return -1:可提现金额不足  -2：操作失败  -3：商户余额不足  -4:提现积分不能为空、负数、0等  
	 *         -5：积分值不正确  -6:提现不能超多上限   1：提现成功
	 */
	public int doWithdraws(Long memberId, Integer score){
		try{
			
			if(memberId == null){
				return -2;
			}
			
			if(score == null || score <=0){
				return -4;//提现积分不能为空、负数、0等
			}
			
			if(score > 2000){
				return -6;
			}
			
			FuziongMemberStatistics fms = fuziongMemberStatisticsService.getByMember(memberId);
			if(fms == null){
				return -2;
			}
			
			score = score * 100;//前端传过来的是元  要转成分
			if(fms.getNowTotalMoney() < score){
				return -5;//积分值不正确
			}
			
			if(fms.getNowTotalMoney() <= 0){
				return -1;//可提现金额不足
			}

			logger.info("微信提现开始：memberId="+memberId);
			boolean resu = false;
			if(score <= 20000){//提现金额小于200块钱  走红包
				resu = sendRedPaper(memberId, score);//向微信发出通知  发送红包  如果红包发送失败  就显示是商户余额不足
			}else{
				resu = companySendRedPaper(memberId, score);//向微信发出通知  走企业支付  支付失败  就显示是商户余额不足
			}

			if(!resu){
				return -3;//商户余额不足
			}
			
			//新增一条提现记录
			WithdrawsRecords wr = new WithdrawsRecords();
			wr.setMemberId(memberId);
			wr.setMoney(score);
			super.save(wr);
			logger.info("提现申请记录添加成功，WithdrawsRecords="+JSON.toJSONString(wr));
			
			//修改统计表中会员的可提现金额
			FuziongMemberStatistics fms2 = new FuziongMemberStatistics();
			fms2.setMemberId(memberId);
			fms2.setNowTotalMoney(score*-1);
			fms2.setWithdrawTotalMoney(score);
			fuziongMemberStatisticsService.updateNowTotalMoneyByMemberId(fms2);//修改可提现的金额
			
			//添加一条支出记录
			IncomeExpenditureRecords ier = new IncomeExpenditureRecords();
			ier.setMemberId(memberId);
			ier.setMoney(score*-1);//  以分为单位
			ier.setObjType(FuzionConstants.IncomeExpenditure.WITHDRAWS);//类型为申请提现
			ier.setObjId(String.valueOf(memberId));
			boolean result = incomeExpenditureRecordsService.insert(ier);
			if(!result){
				return -2;
			}
			
			//推送提现成功信息
			FuzionMemberRedisDto redis_fuzion_member = fuzionMemberService.getFuzionMemberRedisDto(memberId);
			if(redis_fuzion_member != null && StringUtils.isNotBlank(redis_fuzion_member.getOpenId())){
				WeixinSendInfo ws = weixinSendInfoService.getByKey("weixin_withdraws_success");
				String message = ws.getValue().replace("{money}", String.valueOf(score/100));
				SendInfoThread.sendMessage(redis_fuzion_member.getAppId(), redis_fuzion_member.getAppSecret(), 
						redis_fuzion_member.getOpenId(), message);
			}
			
			return 1;
		}catch(Exception e){
			e.printStackTrace();
			logger.error("WithdrawsRecordsService.doWithdraws error", e);
		}
		return -2;
	}

	/**
	 * 新增
	 * @param withdrawsRecords 值都是从表中取出的  所以金额的单位不用转换
	 * @return
	 */
	public boolean insert(WithdrawsRecords withdrawsRecords){
		Long withdrawsRecordsId=null;
		Long ierId = null;
		try{
			
			super.save(withdrawsRecords);
			withdrawsRecordsId = withdrawsRecords.getId();
			logger.info("提现申请记录添加成功，WithdrawsRecords="+JSON.toJSONString(withdrawsRecords)+"，添加时间="+new Date());
			
			//修改统计表中的可提现金额
			FuziongMemberStatistics fms = new FuziongMemberStatistics();
			fms.setMemberId(withdrawsRecords.getMemberId());
			fms.setNowTotalMoney(withdrawsRecords.getMoney()*-1);
			fms.setWithdrawTotalMoney(withdrawsRecords.getMoney());
			fuziongMemberStatisticsService.updateNowTotalMoneyByMemberId(fms);//修改可提现的金额
			
			//添加一条支出记录
			IncomeExpenditureRecords ier = new IncomeExpenditureRecords();
			ier.setMemberId(withdrawsRecords.getMemberId());
			ier.setMoney(withdrawsRecords.getMoney()*-1);//  以分为单位
			ier.setObjType(FuzionConstants.IncomeExpenditure.WITHDRAWS);//类型为申请提现
			ier.setObjId(String.valueOf(withdrawsRecords.getMemberId()));
			boolean result = incomeExpenditureRecordsService.insert(ier);
			ierId = ier.getId();
			if(!result){//添加记录失败 
				super.delete(withdrawsRecords.getId());//添加记录失败时 删除上一步的提现申请
				logger.warn("WithdrawsRecordsService.insert:添加收支记录明细失败,IncomeExpenditureRecords="+ier);
				return false;
			}
			
			boolean resu = companySendRedPaper(withdrawsRecords.getMemberId(), withdrawsRecords.getMoney());//向微信发出通知  发送红包
			if(!resu){
				logger.warn("通知微信发送红包失败，WithdrawsRecords="+JSON.toJSONString(withdrawsRecords)+"，通知时间="+new Date());
				return false;
			}
			logger.info("通知微信发送红包成功，WithdrawsRecords="+JSON.toJSONString(withdrawsRecords)+"，通知时间="+new Date());
			
			return true;
		}catch(Exception e){
			e.printStackTrace();
			if(withdrawsRecordsId != null){
				super.delete(withdrawsRecords.getId());
			}
			if(ierId != null){
				incomeExpenditureRecordsService.delete(ierId);
			}
			
			logger.error("WithdrawsRecordsService.insert err", e);
		}
		return false;
	}
	
	/**
	 * 审核提现记录
	 * @param id
	 * @return
	 */
	public boolean checkWithdrawsRecords(Long id){
		try{
			
			super.update(id, "type", FuzionConstants.TYPE_TWO);//将状态修改为已发放
			
			logger.info("提现申请发放成功，WithdrawsRecords.id="+id+"，发放时间="+new Date());
			WithdrawsRecords withdrawsRecords = super.getById(id);
			
			IncomeExpenditureRecords ier = new IncomeExpenditureRecords();
			ier.setMemberId(withdrawsRecords.getMemberId());
			ier.setMoney((withdrawsRecords.getMoney()*100)*-1);//前端传的是元为单位  扩大100倍  以分为单位
			ier.setObjType(FuzionConstants.IncomeExpenditure.WITHDRAWS);//类型为申请提现
			ier.setObjId(String.valueOf(withdrawsRecords.getMemberId()));
			boolean result = incomeExpenditureRecordsService.insert(ier);
			if(!result){//添加记录失败 将状态修改回去
				super.update(id, "type", FuzionConstants.TYPE_ONE);
				logger.warn("WithdrawsRecordsService.insert:添加收支记录明细失败,IncomeExpenditureRecords="+ier);
				return false;
			}
			return true;
		}catch(Exception e){
			e.printStackTrace();
			logger.error("WithdrawsRecordsService.checkWithdrawsRecords err", e);
		}
		return false;
	}
	
	/**
	 * 根据会员ID  获取已审核发放的提现
	 * @param memberId
	 * @return
	 */
	public List<WithdrawsRecords> getListByMemberId(Long memberId){
		Map<String, Object> param = Maps.newHashMapWithExpectedSize(2);
		param.put("memberId", memberId);
		param.put("orderByKey", "-id");
		List<WithdrawsRecords> ll = super.list(param);
		ll.forEach(ls ->{
			ls.setCheckTime(TimeUtils.format(new Date(ls.getUt()), "yyyy/MM/dd"));
			ls.setMoney(ls.getMoney()/100);//除以100  将分转化为元
		});
		return ll;
	}
	
	/**
	 * 发送红包
	 * @param memberId
	 * @return
	 */
	public boolean sendRedPaper(Long memberId, int amount){
		try{
			FuzionMember fm = fuzionMemberService.getById(memberId);
			if(StringUtils.isBlank(fm.getWeixinId())){
				return false;//失败
			}
			WeixinConfig wc = weixinConfigService.getById(Long.parseLong(fm.getWeixinId()));
			// 私钥密码=商户号
			String password = wc.getMchId();
			// 密钥路径
			String keyStorePath = resourceHolder.getStringValue("fileUploadPath")+wc.getKeyStore();

			WeixinShopConfig ws = new WeixinShopConfig();
			ws.setNonceStr(DateFormatUtils.format(new Date(), "yyyyMMdd") + RandomUtils.buildRandom(6));//随机数
			ws.setMchBillno(password + DateFormatUtils.format(new Date(), "yyyyMMdd") + RandomUtils.getIntRandom(10));
			ws.setMchId(wc.getMchId());
			ws.setWxappId(wc.getAppId());
			ws.setSendName(wc.getName());
			ws.setOpenId(fm.getOpenId());
			ws.setTotalAmount(amount);
			ws.setTotalNum(1);
			ws.setWishing("恭喜发财");
			ws.setClientIp("115.192.115.16");
			ws.setActName("大乱斗");
			ws.setRemark("恭喜发财");
			ws.setKey(wc.getMcKkey());
			String sign = SignUtil.signToMD5(ws.sort());
			ws.setSign(sign);
			// 发起请求
			String resTemp = ClientCustomSSL.post(keyStorePath, password, WeixinConstants.URL.SEND_REDPACK_URL, ws.toXml());

			Map<String, Object> result = XMLUtil.doXMLParse(resTemp);
			logger.info("微信红包发送返回信息：" + JSON.toJSONString(result));
			if(!result.isEmpty()){
				String succ = (String) result.get("result_code");
				logger.info("微信红包发送结果：" + StringUtils.equals(succ, "SUCCESS"));
				if(StringUtils.equals(succ, "SUCCESS")){
					return true;
				}
			}
		}catch (Exception e){
			e.printStackTrace();
			logger.error("WithdrawsRecordsService.sendRedPaper error", e);
		}
        return false;
	}
	
	/**
	 * 提现  企业支付，并将记录计入到表中
	 * @param memberId
	 * @param amount:以元为单位
	 * @return
	 */
	public boolean withdrawsSendRedPaperAndLog(Long memberId, int amount){
		boolean result = companySendRedPaper(memberId, amount);
		if(result){
			//增加记录
			
			//修改统计表中的可提现金额
			FuziongMemberStatistics fms = new FuziongMemberStatistics();
			fms.setMemberId(memberId);
			fms.setNowTotalMoney(amount*100*-1);
			fms.setWithdrawTotalMoney(amount);
			fuziongMemberStatisticsService.updateNowTotalMoneyByMemberId(fms);//修改可提现的金额
			
			//添加一条支出记录
			IncomeExpenditureRecords ier = new IncomeExpenditureRecords();
			ier.setMemberId(memberId);
			ier.setMoney(amount*100*-1);//前端传的是元为单位  扩大100倍  以分为单位
			ier.setObjType(FuzionConstants.IncomeExpenditure.WITHDRAWS);//类型为申请提现
			ier.setObjId(String.valueOf(memberId));
			boolean result2 = incomeExpenditureRecordsService.insert(ier);
			if(!result2){//添加记录失败 
				logger.warn("WithdrawsRecordsService.withdrawsSendRedPaperAndLog:添加收支记录明细失败,IncomeExpenditureRecords="+ier);
				return false;
			}
			return true;
		}
		return false;
	}
	
	/**
	 * 企业支付
	 * @param memberId
	 * @param amount
	 * @return
	 */
	public boolean companySendRedPaper(Long memberId, int amount){
		FuzionMember fm = fuzionMemberService.getById(memberId);
		if(StringUtils.isBlank(fm.getWeixinId())){
			return false;//失败
		}
		WeixinConfig wc = weixinConfigService.getById(Long.parseLong(fm.getWeixinId()));
        // 密钥路径
        String keyStorePath = resourceHolder.getStringValue("fileUploadPath")+wc.getKeyStore();
        
        CompanyPayConfig cpc = new CompanyPayConfig();
        cpc.setMchAppId(wc.getAppId());
        cpc.setMchId(wc.getMchId());
        cpc.setNonceStr(RandomUtils.getIntRandom(32));
        cpc.setPartnerTradeNo(RandomUtils.getIntRandom(32));
        cpc.setOpenId(fm.getOpenId());
        cpc.setAmount(amount);
        cpc.setDesc("欢迎您继续大乱斗");
        cpc.setSpbillCreateIp("114.55.86.27");
        cpc.setCheckName("NO_CHECK");
        cpc.setKey(wc.getMcKkey());
        
        String result = CompanyPayUtils.send(cpc, keyStorePath);
        logger.info("企业支付结果：" + result);
        if(StringUtils.equals(result, "SUCCESS")){
        	return true;
        }
        return false;
	}
	
}






































